#!/usr/bin/env python

# ------------------------------------------------------------
# ::                                                WIGA-SOFT                                             ::
# ------------------------------------------------------------
# department.py
# Module for department reports
# Created by: Gedas, Wiktor
# Version: 1.0
# ------------------------------------------------------------

from __future__ import division
from pao.models import Project, Employee, Task, Department, Budget
from pao.reports.project import addMonth
from django.db.models import *
from datetime import *

def departmentManagerReport(departmentID, start=None, end=None):
    """
    Input: DepartmentID (department), StartPeriod? (start), EndPeriod? (end) 
    Output: Zodynas (Dictionary) 
    {
        'department': <Skyriaus pavadinimas/numeris>,
        'departmentId': <Skyriaus numeris>
        'total': <Viso skyriaus darbuotoju isdirbta projektuose>,
        'local': <Kiek laiko skyriaus darbuotojai skyre savo skyriaus projektams>,
        'foreign': <Kiek laiko skyriaus darbuotojai skyre kitu skyriu projektams>,
        'others': { <Skyriaus numeris>: <Kiek kitas skyrius isdirbo prie sio skyriaus projektu>, ....... }
        'freetime': <Kiek laiko skyriaus darbuotojai nedirbo jokiame projekte>,
        'freepercent': <Kiek procentu laisvas laikas sudaro nuo viso (teorinio) valandu skaiciaus>,
		'manager': <Skyriaus vadovas>

    }
    """
    dep = Department.objects.filter(id = departmentID).values("id","name")
    departmentEmployeeHours = Task.objects.filter(employee__department__id = departmentID)
    departmentHoursForSelf = Task.objects.filter(employee__department__id = departmentID, project__manager__department__id = departmentID)
    departmentHoursForOthers = Task.objects.filter(employee__department__id = departmentID)
    others = Task.objects.filter(project__manager__department__id = departmentID)
    departmentEmployeeCout = Task.objects.filter(employee__department__id = departmentID)

    manager = Department.objects.filter(id = departmentID).values("manager__id__username")

    if start != None:
        departmentEmployeeHours = departmentEmployeeHours.filter(date__gte = start)
        departmentHoursForSelf = departmentHoursForSelf.filter(date__gte = start)
        departmentHoursForOthers = departmentHoursForOthers.filter(date__gte = start)
        others = others.filter(date__gte = start)
        departmentEmployeeCout = departmentEmployeeCout.filter(date__gte = start)
        
    if end != None:
        departmentEmployeeHours = departmentEmployeeHours.filter(date__lte = end)
        departmentHoursForSelf = departmentHoursForSelf.filter(date__lte = end)
        departmentHoursForOthers = departmentHoursForOthers.filter(date__lte = end)
        others = others.filter(date__lte = end)
        departmentEmployeeCout = departmentEmployeeCout.filter(date__lte = end)
        
    departmentEmployeeHours = departmentEmployeeHours.aggregate(Sum("workhours"))
    departmentHoursForSelf=departmentHoursForSelf.aggregate(Sum("workhours"))
    departmentHoursForOthers=departmentHoursForOthers.exclude(project__manager__department__id = departmentID).aggregate(Sum("workhours"))
    others = others.exclude(employee__department__id = departmentID).values("employee__department","employee__department__name").annotate(Sum("workhours"))
    departmentEmployeeCout = departmentEmployeeCout.aggregate(Count("workhours"))
    
    if departmentEmployeeHours["workhours__sum"] == None:
        departmentEmployeeHours["workhours__sum"] = 0
    if departmentHoursForSelf["workhours__sum"] == None:
        departmentHoursForSelf["workhours__sum"] = 0
    if departmentHoursForOthers["workhours__sum"] == None:
        departmentHoursForOthers["workhours__sum"] = 0
    list = {}
    other = []
    list["department"] = dep[0]["name"]
    list["total"] = departmentEmployeeHours["workhours__sum"]
    list["local"] = departmentHoursForSelf["workhours__sum"]
    list["foreign"] = departmentHoursForOthers["workhours__sum"]

    list["manager"] = manager[0]["manager__id__username"]

    i = 0
    for e in others:
        temp = {}
        othersDepartment = e["employee__department__name"]
        temp["departmentId"] = e["employee__department"]
        temp["department"] = othersDepartment
        temp["timeTotal"] = e["workhours__sum"]
        other += [temp]
        i += 1
    list["others"] = other
    list["freetime"] = (departmentEmployeeCout["workhours__count"]*160-departmentEmployeeHours["workhours__sum"])
    if departmentHoursForOthers["workhours__sum"] == 0:
        list["freepercent"] = None
    else:
        list["freepercent"] = 100 - departmentEmployeeHours["workhours__sum"] / (departmentEmployeeCout["workhours__count"] * 1.6)
    list["departmentId"] = departmentID
    return list
    
def departmentProjectsReport(departmentID, start=None, end=None):
    """
    Input: DepartmentID (department), StartPeriod? (start), EndPeriod? (end) 
    Output: Table (List of Dictionaries) 
    [
        {'project': <Projekto pavadinimas/kodas>, 
            'projectId': <Projekto kodas>, 
            'manager': <Projekto vadovas>,
            'department': <Projekto vadovo skyrius>,
            'departmentId': <Projekto vadovo skyriaus numeris>,
            'started': <Kada projektas prasidejo>,
            'finished': <Kada projektas baigesi>,
            'local': <Kiek projekte isdirbo sio skyriaus dalyviai>,
            'foreign': <Kiek projekte isdirbo kitu skyriu dalyviai>,
            'total': <Kiek projekte isdirbo visi dalyviai>
        },
        { .... }
        { .... }
    ]
    """
    #self project report
    project = Task.objects.filter(project__manager__department__id = departmentID).values("project__id","project__name" ,  "project__manager__id__username", "project__manager__department__id","project__manager__department__name").annotate(Min("date"), Max("date")).order_by("project__id")
    hoursSelf = Task.objects.filter(project__manager__department__id = departmentID,employee__department__id = departmentID)
    hoursTotal = Task.objects.filter( project__manager__department__id = departmentID)
    
    if start != None:
        hoursSelf = hoursSelf.filter(date__gte = start)
        hoursTotal = hoursTotal.filter(date__gte = start)
    if end != None:
        hoursSelf = hoursSelf.filter(date__lte = end)
        hoursTotal = hoursTotal.filter(date__lte = end)
        
        
    hoursSelf = hoursSelf.values("project__id","project__name").annotate(Sum("workhours"))
    hoursTotal = hoursTotal.values("project__id").annotate(Sum("workhours")).order_by("project__manager__department__id")
    


    list = []
    
    for total in hoursTotal:
        pr = None
        for prj in project:
            if prj["project__id"] == total["project__id"]:
                pr = prj
        
        self = 0
        for dep in hoursSelf:
            if pr["project__id"] == dep["project__id"]:
                self = dep["workhours__sum"]

        if total["workhours__sum"] == None:
            totalh=0
        else:
            totalh = total["workhours__sum"]
        if self == None:
            self = 0

        if pr["date__max"] == date(date.today().year, date.today().month, 01):
            finish = None
        else:
             finish = pr["date__max"]

        prName = pr["project__name"]
        dep = pr["project__manager__department__name"]
        list +=[{"project": prName,"projectId":pr["project__id"], "manager":pr["project__manager__id__username"], "department": dep,"departmentId":departmentID, "started": pr["date__min"], "finished": finish, "local": self, "foreign": totalh-self, "total":totalh}]      

        
    #other department repors inveolved with specified
    project = Task.objects.exclude(project__manager__department__id = departmentID).values("project__id","project__name", "project__manager__id__username", "project__manager__department__id", "project__manager__department__name").annotate(Min("date"), Max("date")).order_by("project__manager__department__id","project__id")
    hoursSelf = Task.objects.exclude(project__manager__department__id = departmentID).filter(employee__department__id = departmentID)
    hoursTotal = Task.objects.exclude(project__manager__department__id = departmentID)
    
    if start != None:
        hoursSelf = hoursSelf.filter(date__gte = start)
        hoursTotal = hoursTotal.filter(date__gte = start)
    if end != None:
        hoursSelf = hoursSelf.filter(date__lte = end)
        hoursTotal = hoursTotal.filter(date__lte = end)
        
        
    hoursSelf = hoursSelf.values("project__id","project__name").annotate(Sum("workhours"))
    hoursTotal = hoursTotal.values("project__id","project__name").annotate(Sum("workhours")).order_by("project__manager__department__id","project__id")
    
    for total in hoursTotal:
        pr = None
        for prj in project:
            if prj["project__id"] == total["project__id"]:
                pr = prj
        
        self = 0
        for dep in hoursSelf:
            if pr["project__id"] == dep["project__id"]:
                self = dep["workhours__sum"]

        if total["workhours__sum"] == None:
            totalh=0
        else:
            totalh = total["workhours__sum"]
        if self == None:
            self = 0

        if pr["date__max"] == date(date.today().year, date.today().month, 01):
            finish = None
        else:
             finish = pr["date__max"]
        if self!=0:
            prName = pr["project__name"]
            dep = pr["project__manager__department__name"]
            list +=[{"project": prName,"projectId":pr["project__id"], "manager":pr["project__manager__id__username"], "department": dep,"departmentId":departmentID, "started": pr["date__min"], "finished": finish, "local": self, "foreign": totalh-self, "total":totalh}]      

    return list
    

def departmentBudgetReport(departmentID, start=None, end=None):
    """
    Input: DepartmentID (department), StartPeriod? (start), EndPeriod? (end) 
    Output: Table (List of Dictionaries)
    
    [
        {'date': <Metai-Menuo>,
        'total': <Kiek biudzeto skirta>,
        'used': <Kiek biudzeto isnaudota>,
        'left': <Kiek biudzeto liko>,
        'percent': <Likutis procentais> },
        { .... },
        { .... }
    ]
    """
    
    workhours = Task.objects.filter(project__manager__department__id = departmentID)
    budget = Budget.objects.filter(project__manager__department__id = departmentID)

    
    if start != None:
        workhours = workhours.filter(date__gte = start)
        budget = budget.filter(date__gte = start)

    if end != None:
        workhours = workhours.filter(date__lte = end)
        budget = budget.filter(date__lte = end)

    whDate = workhours.aggregate(Min("date"),Max("date"))   
    bdDate = budget.aggregate(Min("date"),Max("date"))  
    
    if whDate["date__min"] == None:
        whDate = bdDate
    if bdDate["date__min"] == None:
        bdDate = whDate
    if bdDate["date__min"] == None:
        return []
    if whDate["date__min"] > bdDate["date__min"]:
        start = bdDate["date__min"]
    else:
        start = whDate["date__min"]

    if whDate["date__max"] < bdDate["date__max"]:
        end = bdDate["date__max"]
    else:
        end = whDate["date__max"]

    workhours = workhours.values("date").annotate(Sum("workhours"))
    budget = budget.values("date").annotate(Sum("workhours"))
    

    if date.today().year % 4 == 0:
        year = timedelta(days=366)
    else:
        year = timedelta(days=365)

    dif_month = (end.year - start.year) * 12 - end.month + start.month
    list = []
    
    while start <= end:
        bdg = {"workhours__sum": 0}
        for bd in budget:
            if bd["date"] == start:
                bdg = bd
        
        who = {"workhours__sum": 0}
        for wh in workhours:
            if start == wh["date"]:
                who = wh

        if who["workhours__sum"] == None:
            who["workhours__sum"] = 0
        if bdg["workhours__sum"] == None:
            bdg["workhours__sum"] = 0

        if bdg["workhours__sum"] == 0: 
            percent = None
        else:
            percent = 100 - (100 * who["workhours__sum"] / bdg["workhours__sum"])
        list += [{"date": start,"total": bdg["workhours__sum"],"used": who["workhours__sum"],"left": bdg["workhours__sum"] - who["workhours__sum"],"percent": percent}]
        start = add_months(start)
    
    return list
    
def add_months(input, months = 1):



    year, month, day = input.timetuple()[:3]
    new_month = month + months
    
    return date(year + int((new_month - 1) / 12), (new_month - 1) % 12 + 1, day)


def departmentLoadReport(department, start=None, end=None):
    """
    Input: DepartmentID(department), StartPeriod? (start), EndPeriod? (end) 
    Output: Table (List of Dictionaries)
    [
      {'date': <Metai-Menuo>,
       'workers': <Darbuotoju skaicius ta menesi, tame skyriuje>,
       'resource': <Max. valandos - resursas (Darbuotoju skaicius x 160)>,
       'budget': <Biudzetas skirtas siam laikotarpiui, sio skyriaus projektams>,
       'percent': <Kokia dalis resoursu padengta biudzetu>},
      { ... }
    ]
    """
    
    if start is None:
        start = date(1990, 1, 1)
    if end is None:
        end = date.today()
    result = []
    departmentTasks = Task.objects.filter(employee__department = department)
    departmentTasks = departmentTasks.filter(date__gte = start)
    departmentTasks = departmentTasks.filter(date__lte = end)
    dates = []
    for e in departmentTasks:
        if e.date not in dates:
            if e.date >= start:
                if e.date <= end:
                    dates.append(e.date)
    dates.sort()
    if len(dates) > 0:
        e = min(dates)
        endDate = max(dates)
        while e <= endDate:
            tmpDepartmentTasks = departmentTasks.filter(date = e)
            workers = []
            workhours = 0
            for i in tmpDepartmentTasks:
                if i.employee not in workers:
                    workers.append(i.employee)
            tmpBudget = Budget.objects.filter(date = e)
            tmpBudget = tmpBudget.filter(project__manager__department = department)
            for i in tmpBudget:
                workhours += i.workhours
            tmpRez = {}
            workerCount = len(workers)
            tmpRez['date'] = e
            tmpRez['workers'] = workerCount
            tmpRez['resource'] = workerCount * 160
            tmpRez['budget'] = workhours
            if workerCount != 0:
                tmpRez['percent'] = (workhours * 100) / (workerCount * 160)
            else:
                tmpRez['percent'] = None
            result.append(tmpRez)
            e = addMonth(e)
    return result  
